﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using System.IO;

namespace StarlightEngine.Editor
{
    public partial class Form1 : Form
    {
        AboutForm about = new AboutForm();
        EditorGame game;
        Microsoft.Xna.Framework.Graphics.Color toSet = Microsoft.Xna.Framework.Graphics.Color.White;
        public Form1()
        {
            InitializeComponent();
            game = new EditorGame();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            propertyGrid1.CommandsVisibleIfAvailable = true;
            propertyGrid1.PropertyValueChanged += new PropertyValueChangedEventHandler(propertyGrid1_PropertyValueChanged);           
            //Wire up mouse events.
            xnaViewer1.MouseEnter += new EventHandler(xnaViewer1_MouseEnter);
            xnaViewer1.MouseLeave += new EventHandler(xnaViewer1_MouseLeave);
            //Run the game.
            xnaViewer1.RunGame(game);            
            //Add blank texture.
            listBox1.Items.Clear();
            listBox1.Items.Add("Blank :: Engine");
            listBox1.SelectedIndex = 0;

            //Setup tooltips
            ToolTip t = new ToolTip();
            //Textures.
            t.SetToolTip(listBox1, "Contains all the current textures within the scene.");
            //Add texture button
            t.SetToolTip(button2, "Adds a texture with the specified paramaters");
            //Remove button
            t.SetToolTip(button3, "Removes the selected texture.");
            //Texture name
            t.SetToolTip(textBox1, "The name of the texture to be added.");
            t.SetToolTip(textBox2, "The path relative to the current directory of the texture to add.");
            //Browse
            t.SetToolTip(button1, "Browse for a texture.");

            //Nodes box
            t.SetToolTip(groupBox2, "A view of all the nodes in the scene,\naswell as special properties such as the scene name.");

            //Node tree view.
            t.SetToolTip(treeView1, "All the nodes within the scene.");

            //Delte node button
            t.SetToolTip(button5, "Removes the currently selected node.");

            //Properties
            t.SetToolTip(propertyGrid1, "Propertys of the currently \nselected node in the treeview (Above)");

            //Camera zoom
            t.SetToolTip(trackBar1, "The current zoom of the scene.");

            //Camera box
            t.SetToolTip(groupBox4, "Controls the zoom, rotation and position of the camera.");

            //New node settings
            t.SetToolTip(groupBox1, "Controls the size, rotation and color of newly created nodes.");

            this.Text = String.Format("{0} Editor", StarlightEngine.Settings.EngineName);
        }

        void xnaViewer1_MouseLeave(object sender, EventArgs e)
        {
            Cursor.Show();
            game.AllowNodeCreation = false;
        }

        void xnaViewer1_MouseEnter(object sender, EventArgs e)
        {
            Cursor.Hide();
            game.AllowNodeCreation = true;
        }


        void RecreateNodesNode()
        {
            treeView1.Nodes[0].Nodes.Clear();
            foreach (StarlightEngine.Node n in game.Nodes.Values)
            {
                treeView1.Nodes[0].Nodes.Add(n.NameInScene);
            }
        }       

        void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            //We should re add all nodes, incase a name has changed.
            if (e.ChangedItem.Label == "NameInScene")
            {
                //Renamed a node.
                game.NodeToHighlight = "";
                RecreateNodesNode();
            }
            if (e.ChangedItem.Label == "Name")
            {
                //Scene has changed name.               
                this.Text = String.Format("{0} Editor - {1}", StarlightEngine.Settings.EngineName, game.EditorScene.Name);
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                game.SetTexture(listBox1.SelectedItem.ToString().Split()[0]);
            }
            catch(NullReferenceException){ }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveScene();
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadScene();
        }

        public void SaveScene()
        {
            notifyIcon1.ShowBalloonTip(100, "Saving", StarlightEngine.Settings.EngineName + " is saving the scene.", ToolTipIcon.Info);
            SaveFileDialog f = new SaveFileDialog();
            f.DefaultExt = "zhds";
            f.AddExtension = true;
            f.Filter = StarlightEngine.Settings.EngineName + " Scene Files (*.ssf)|*.ssf";

            //Make the maps folder if it isnt there.
            string path = System.IO.Directory.GetCurrentDirectory() + "\\Content\\Scenes";
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            f.Title = "Save Scene...";
            f.InitialDirectory = path;

            DialogResult s = f.ShowDialog();

            if (s == DialogResult.OK)
            {
                //Okay               
                game.Save(f.FileName);
                notifyIcon1.ShowBalloonTip(100, "Saved", StarlightEngine.Settings.ShortEngineName + " has finished saving the scene..", ToolTipIcon.Info);


            }
            else
                notifyIcon1.ShowBalloonTip(100, "Saving", "User cancelled saving.", ToolTipIcon.Warning);


        }

        public void LoadScene()
        {
            notifyIcon1.ShowBalloonTip(100, "Loading", StarlightEngine.Settings.ShortEngineName + " is loading the scene.", ToolTipIcon.Info);
            OpenFileDialog of = new OpenFileDialog();
            of.Title = "Load Scene...";
            of.DefaultExt = "zhds";
            of.Filter = StarlightEngine.Settings.EngineName + " Scene Files (*.ssf)|*.ssf";
            of.AddExtension = true;
            string path = System.IO.Directory.GetCurrentDirectory() + "\\Content\\Scenes";
            of.InitialDirectory = path;
            DialogResult res = of.ShowDialog();
            if (res == DialogResult.OK)
            {
                game.NodeToHighlight = "";
                //We have a filename.
                propertyGrid1.SelectedObject = "";
                game.EditorScene.Clear();
                game.Load(of.FileName);
                //Reset the camera.
                game.ResetCamera();
                

                //Create the texture tree again.
                listBox1.Items.Clear();
                listBox1.Items.Add("Blank :: Engine");
                foreach (KeyValuePair<string, string> texture in game.EditorScene.RequiredTextures)
                {
                    string name = texture.Key;
                    string paths = texture.Value;

                    if (!listBox1.Items.Contains(name + " :: " + paths))
                        listBox1.Items.Add(name + " :: " + paths);
                    else
                        MessageBox.Show("Already have texture.");                   

                }
                listBox1.SelectedIndex = 0;
                RecreateNodesNode();

                notifyIcon1.ShowBalloonTip(100, "Loaded", StarlightEngine.Settings.ShortEngineName + " has finished loading the scene.", ToolTipIcon.Info);
                this.Text = String.Format("{0} Editor - {1}", StarlightEngine.Settings.EngineName, game.EditorScene.Name);

            }
            else
                notifyIcon1.ShowBalloonTip(100, "Loading", "User cancelled loading.", ToolTipIcon.Warning);
            
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            bool handled = false;
            string path = (treeView1.SelectedNode.FullPath);
            if (path.StartsWith("Scene Properties"))
            {
                propertyGrid1.SelectedObject = game.EditorScene;
                game.NodeToHighlight = "";
                handled = true;
            }
            if(path.StartsWith("Nodes\\"))
            {
                //They selected a node.
                propertyGrid1.SelectedObject = game.Nodes[treeView1.SelectedNode.Text];
                //Lets make the game highlight it.
                game.NodeToHighlight = treeView1.SelectedNode.Text;
                handled = true;
            }
            if (!handled)
                game.NodeToHighlight = "";
            
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (game.HasAddedNode)
            {
                //Update the node view.
                game.LastNode.Scale = float.Parse(textBox3.Text);
                game.LastNode.Rotation = float.Parse(textBox4.Text);
                game.LastNode.DrawColor = new Microsoft.Xna.Framework.Graphics.Color((byte)toSet.R, (byte)toSet.B, (byte)toSet.G, (byte)toSet.A);
                treeView1.Nodes[0].Nodes.Add(game.LastNode.NameInScene);                
                game.HasAddedNode = false;
            }
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            notifyIcon1.ShowBalloonTip(100, "New Scene", "Creating new scene...", ToolTipIcon.Info);
            propertyGrid1.SelectedObject = "";
            game.EditorScene.Clear();
            RecreateNodesNode();
            this.Text = String.Format("{0} Editor - {1}", StarlightEngine.Settings.EngineName, "Untitled*");
            
        }
       

        private void button1_Click(object sender, EventArgs e)
        {            
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.InitialDirectory = Directory.GetCurrentDirectory() + "\\Content";
            DialogResult result = fileDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                //We has a file
                string path = fileDialog.FileName.Replace(Directory.GetCurrentDirectory() + "\\","");                
                textBox2.Text = path.Replace(".xnb","");                
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string path = textBox2.Text;
            string name = textBox1.Text;            
            if (name.Contains(" "))
                MessageBox.Show("Invalid Name");
            else
            {
                game.LoadTexture(name, path);
                if (!listBox1.Items.Contains(name + " :: " + path))
                    listBox1.Items.Add(name + " :: " + path);
                else
                    MessageBox.Show("Already have texture.");
            }           
            
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //Removing a texture.
            //Set to a blank.
            game.SetTexture("");
            //We havent selected 0, so we can safely select the first item.
            int select = 0;
            int remove = listBox1.SelectedIndex;
            if (listBox1.SelectedIndex != 0)
                select = 0;
            else
                select = listBox1.Items.Count - 1;
            listBox1.Items.Remove(listBox1.SelectedItem);
            listBox1.SelectedItem = listBox1.Items[select];
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            try
            {
                game.PlacementScale = float.Parse(textBox3.Text);
            }
            catch { }
        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {
            try
            {
                game.PlacementRotation = float.Parse(textBox4.Text);
            }
            catch { }

        }

        private void button4_Click(object sender, EventArgs e)
        {
            ColorDialog d = new ColorDialog();            
            DialogResult res = d.ShowDialog();
            if (res == DialogResult.OK)
            {
                toSet = new Microsoft.Xna.Framework.Graphics.Color(d.Color.R, d.Color.B, d.Color.G, d.Color.A);
                game.PlacementColor = new Microsoft.Xna.Framework.Graphics.Color((byte)toSet.R, (byte)toSet.B, (byte)toSet.G, (byte)toSet.A);
                textBox5.Text = toSet.R + ":" + toSet.B + ":" + toSet.G + "::" + toSet.A;
            }
        }

        private void aboutZHDEToolStripMenuItem_Click(object sender, EventArgs e)
        {
            about = new AboutForm();
            about.Show();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            about.Close();
            this.Close();            
        }

        private void button5_Click(object sender, EventArgs e)
        {
            game.NodeToHighlight = "";
            //We're deleting a node.
            if(treeView1.SelectedNode.FullPath.StartsWith("Nodes\\"))
            {                
                //Its a node, lets delete it.
                string name = treeView1.SelectedNode.FullPath.Replace("Nodes\\","");                
                game.RemoveNode(name);
                RecreateNodesNode();
                
            }

        }

        private void button6_Click(object sender, EventArgs e)
        {
            game.Move(MoveDirection.Down);
            RedoPosLabel();
        }

        private void button7_Click(object sender, EventArgs e)
        {
            game.Move(MoveDirection.Up);
            RedoPosLabel();
        }

        private void button9_Click(object sender, EventArgs e)
        {
            game.Move(MoveDirection.Left);
            RedoPosLabel();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            game.Move(MoveDirection.Right);
            RedoPosLabel();
        }

        private void button10_Click(object sender, EventArgs e)
        {
            //Reset
            game.ResetCameraPos();
            RedoPosLabel();
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            float val = (float)((float)trackBar1.Value / 10);          
            labelZoom.Text = val.ToString();
            
            game.SetZoom(val);
        }

        private void button11_Click(object sender, EventArgs e)
        {
            //rotate right
            game.Rotate(MoveDirection.Right);
            rotateLabel.Text = "Rotate : " + game.EditorScene.Rotation + " degrees";
        }

        private void button12_Click(object sender, EventArgs e)
        {
            //rotate left
            game.Rotate(MoveDirection.Left);
            rotateLabel.Text = "Rotate : " + game.EditorScene.Rotation + " degrees";
        }

        void RedoPosLabel()
        {
            PosLabel.Text = "Position : X " + game.EditorScene.CameraPosition.X + " Y " + game.EditorScene.CameraPosition.Y;
        }
    }
}
